package zoran.wang;

import zoran.wang.tree.TreeNode;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class CBTInserter {

    // 队列，包含所有可插入的节点
    public Queue<TreeNode> insertRootQueue = new LinkedList<>();

    // root
    private TreeNode root;

    // 构造器，创建对象时，初始化 this.root，并层序遍历整个二叉树，初始化 resentRootQueue，给 insert 方法使用
    public CBTInserter(TreeNode root) {
        this.root = root;

        // 层序遍历
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);

        while (!q.isEmpty()) {

            TreeNode cur = q.poll();
            if (cur.left != null) q.offer(cur.left);
            if (cur.right != null) q.offer(cur.right);
            System.out.println(cur.val);

            // 如果当前节点 cur 左右节点不满，则存入 resentRootQueue
            if (cur.left == null || cur.right == null)
                insertRootQueue.offer(cur);
        }
    }

    /**
     * 向树中插入一个值为 Node.val == val的新节点 TreeNode。
     * 使树保持完全二叉树的状态
     *
     * @param val:插入的值
     * @return 插入节点 TreeNode 的父节点的值
     */
    public int insert(int val) {

        TreeNode newNode = new TreeNode(val);
        TreeNode root = insertRootQueue.peek();

        if (root.left == null) {
            root.left = newNode;
        } else if (root.right == null) {
            root.right = newNode;
            insertRootQueue.poll();
        }

        // 新加入的节点也可以作为插入的新元素的父节点
        insertRootQueue.offer(newNode);

        return root.val;
    }

    public TreeNode get_root() {

        return root;
    }
}

/**
 * Your CBTInserter object will be instantiated and called as such:
 * CBTInserter obj = new CBTInserter(root);
 * int param_1 = obj.insert(val);
 * TreeNode param_2 = obj.get_root();
 */